﻿using System;
using System.Configuration;
using System.Text.RegularExpressions;
using ERP.Framework.Components.Utilities.TracingHelper;

namespace ERP.Framework.Components.Utilities.TypeHelper
{
    /// <summary>
    /// TypeInfo discriptor class
    /// </summary>
    internal class TypeInfo
    {
        #region Constructors

        /// <summary>
        /// Initializes the <see cref="TypeInfo"/> class.
        /// </summary>
        static TypeInfo()
        {
            string msg = "Failed to parse Regex Patten for resolving fully qualified type names";
            try
            {
                Grep = new Regex(Pattern, RegexOptions.CultureInvariant);
            }
            catch (ArgumentException inner)
            {
                TraceUtil.Write("TypeInfo::cctor", "Throwing FrameworkException [{0}]", new object[] { msg });
                throw new ConfigurationException(msg, inner);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TypeInfo"/> class.
        /// </summary>
        public TypeInfo()
        {
            this.Init();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TypeInfo"/> class.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        public TypeInfo(string typeName)
        {
            this.Init();
            this.Parse(typeName);
        }

        #endregion

        #region Members

        private static readonly Regex Grep;
        private const string Pattern = @"(?insx:(?<type>((\w+)\.)+\w+),\s*(?<assembly>((\w+)\.)*\w+) (,\s*     Version=(?<version>(\d+\.?){4}),\s*Culture=(?<culture>[\w-]+),\s*    PublicKeyToken=(?<key>[0-9a-f]{16}) )?)";

        #endregion

        #region Properties

        /// <summary>
        /// Gets the name of the assembly.
        /// </summary>
        /// <value>The name of the assembly.</value>
        public string AssemblyName
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the culture.
        /// </summary>
        /// <value>The culture.</value>
        public string Culture
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the full name.
        /// </summary>
        /// <value>The full name.</value>
        public string FullName
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the public key token.
        /// </summary>
        /// <value>The public key token.</value>
        public string PublicKeyToken
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the version.
        /// </summary>
        /// <value>The version.</value>
        public string Version
        {
            get;
            private set;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Inits this instance.
        /// </summary>
        private void Init()
        {
            this.Version = null;
            this.Culture = null;
            this.PublicKeyToken = null;
        }

        /// <summary>
        /// Parses the specified type name.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        public void Parse(string typeName)
        {
            Match match = Grep.Match(typeName);
            GroupCollection groups = match.Groups;
            if (!(((((match.Success && ((groups.Count == 3) || (groups.Count == 6))) && (groups["type"] != null)) && (groups["assembly"] != null)) && groups["type"].Success) && groups["assembly"].Success))
            {
                string msg = string.Format("Argument 'typeName' value '{0}' cannot be parsed into a fully qualified type name", typeName);
                TraceUtil.Write("TypeInfo::Parse", "Throwing FrameworkException [{0}]", new object[] { msg });
                throw new ConfigurationException(msg);
            }
            this.FullName = typeName;
            this.Name = groups["type"].Value;
            this.AssemblyName = groups["assembly"].Value;
            if (groups.Count == 6)
            {
                this.Version = groups["version"].Value;
                this.Culture = groups["culture"].Value;
                this.PublicKeyToken = groups["key"].Value;
            }
        }

        #endregion

    }
}
